#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import socket
import threading
import json
import sqlite3
import time
import re
import logging
import imaplib
import email
import os
import sys
import webbrowser
from email.header import decode_header
from datetime import datetime, timedelta
from flask import Flask, render_template, request, jsonify
from apscheduler.schedulers.background import BackgroundScheduler
import requests
from alibabacloud_dysmsapi20170525.client import Client as Dysmsapi20170525Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_dysmsapi20170525 import models as dysmsapi_20170525_models
from alibabacloud_tea_util import models as util_models

# 系统托盘相关导入
try:
    import pystray
    from PIL import Image, ImageDraw
    TRAY_AVAILABLE = True
except ImportError:
    TRAY_AVAILABLE = False
    print("警告: 系统托盘功能不可用，请安装 pystray 和 Pillow 库")

app = Flask(__name__)
app.secret_key = 'syslog_push_secret_key'

# 全局配置
CONFIG = {
    'syslog_port': 514,  # 标准Syslog端口
    'web_port': 5000,
    'alert_keywords': ['error', 'critical', 'alert', 'emergency'],
    'max_logs': 10000,
    
    # 钉钉配置
    'dingtalk_enabled': False,
    'dingtalk_webhook': '',
    'dingtalk_keywords': '',
    
    # 企业微信配置
    'wechat_enabled': False,
    'wechat_webhook': '',
    'wechat_mentioned_list': '',
    
    # 飞书配置
    'feishu_enabled': False,
    'feishu_webhook': '',
    'feishu_secret': '',
    'feishu_at_users': '',
    
    # 阿里云短信配置
    'sms_enabled': False,
    'aliyun_access_key': '',
    'aliyun_access_secret': '',
    'aliyun_sign_name': '',
    'aliyun_template_code': '',
    'phone_numbers': [],
    
    # 邮件采集配置
    'email_enabled': False,
    'email_check_interval': 60,  # 检查间隔（秒）
    'email_accounts': [
        # {
        #     'name': '邮箱1',
        #     'enabled': True,
        #     'server': 'imap.example.com',
        #     'port': 993,
        #     'use_ssl': True,
        #     'username': 'user@example.com',
        #     'password': 'password',
        #     'keywords': ['告警', 'alert', 'error'],
        #     'sender_filter': '',  # 发件人过滤
        #     'subject_filter': ''  # 主题过滤
        # }
    ],
    
    # Webhook配置
    'webhook_enabled': False,
    'webhook_path': '/webhook/alert',
    'webhook_token': ''
}

# 统计数据
STATS = {
    'received_logs': 0,
    'sent_alerts': 0,
    'failed_alerts': 0,
    'checked_emails': 0,
    'email_alerts': 0,
    'start_time': datetime.now()
}

# 全局变量
logs_buffer = []
alerts_buffer = []
service_logs = []
email_logs = []  # 邮件日志存储
webhook_logs = []  # Webhook日志存储

# 系统托盘相关变量
tray_icon = None
flask_thread = None
service_running = False

# 配置保存函数
def save_config():
    """保存配置到文件"""
    try:
        with open('config.json', 'w', encoding='utf-8') as f:
            json.dump(CONFIG, f, ensure_ascii=False, indent=2)
    except Exception as e:
        print(f"保存配置失败: {str(e)}")

# 配置加载函数
def load_config():
    """从文件加载配置"""
    global CONFIG
    try:
        with open('config.json', 'r', encoding='utf-8') as f:
            file_config = json.load(f)
            CONFIG.update(file_config)
            print(f"配置加载成功，Syslog端口: {CONFIG['syslog_port']}")
    except FileNotFoundError:
        print("配置文件不存在，使用默认配置")
        save_config()  # 创建默认配置文件
    except Exception as e:
        print(f"加载配置失败: {str(e)}，使用默认配置")

class EmailCollector:
    def __init__(self):
        self.running = False
        self.thread = None
        self.scheduler = BackgroundScheduler()
        self.last_check_times = {}  # 记录每个邮箱的最后检查时间
        
    def start(self):
        """启动邮件采集服务"""
        if not CONFIG.get('email_enabled', False):
            return False
            
        try:
            self.running = True
            # 启动定时任务
            interval = CONFIG.get('email_check_interval', 60)
            self.scheduler.add_job(
                func=self.check_all_emails,
                trigger='interval',
                seconds=interval,
                id='email_check'
            )
            self.scheduler.start()
            self._log_service("邮件采集服务启动成功")
            return True
        except Exception as e:
            self._log_service(f"邮件采集服务启动失败: {str(e)}")
            return False
    
    def stop(self):
        """停止邮件采集服务"""
        self.running = False
        if self.scheduler.running:
            self.scheduler.shutdown()
        self._log_service("邮件采集服务已停止")
    
    def check_all_emails(self):
        """检查所有配置的邮箱"""
        if not self.running:
            return
            
        accounts = CONFIG.get('email_accounts', [])
        for account in accounts:
            if account.get('enabled', False):
                try:
                    self.check_email_account(account)
                except Exception as e:
                    self._log_service(f"检查邮箱 {account.get('name', 'Unknown')} 失败: {str(e)}")
    
    def check_email_account(self, account):
        """检查单个邮箱账户"""
        global STATS
        
        account_name = account.get('name', 'Unknown')
        server = account.get('server')
        port = account.get('port', 993)
        use_ssl = account.get('use_ssl', True)
        username = account.get('username')
        password = account.get('password')
        keywords = account.get('keywords', [])
        sender_filter = account.get('sender_filter', '')
        subject_filter = account.get('subject_filter', '')
        
        if not all([server, username, password]):
            self._log_service(f"邮箱 {account_name} 配置不完整")
            return
        
        try:
            # 连接邮箱服务器
            if use_ssl:
                mail = imaplib.IMAP4_SSL(server, port)
            else:
                mail = imaplib.IMAP4(server, port)
            
            mail.login(username, password)
            mail.select('INBOX')
            
            # 获取最后检查时间
            last_check = self.last_check_times.get(account_name)
            if last_check is None:
                # 首次检查，只检查最近1小时的邮件
                last_check = datetime.now() - timedelta(hours=1)
            
            # 搜索新邮件
            since_date = last_check.strftime('%d-%b-%Y')
            search_criteria = f'(SINCE "{since_date}" UNSEEN)'
            
            status, messages = mail.search(None, search_criteria)
            if status != 'OK':
                self._log_service(f"邮箱 {account_name} 搜索邮件失败")
                return
            
            message_ids = messages[0].split()
            STATS['checked_emails'] += len(message_ids)
            
            for msg_id in message_ids:
                try:
                    self.process_email_message(mail, msg_id, account, keywords, sender_filter, subject_filter)
                except Exception as e:
                    self._log_service(f"处理邮件消息失败: {str(e)}")
            
            # 更新最后检查时间
            self.last_check_times[account_name] = datetime.now()
            
            mail.close()
            mail.logout()
            
        except Exception as e:
            self._log_service(f"连接邮箱 {account_name} 失败: {str(e)}")
    
    def process_email_message(self, mail, msg_id, account, keywords, sender_filter, subject_filter):
        """处理单个邮件消息"""
        global STATS, email_logs
        
        # 获取邮件内容
        status, msg_data = mail.fetch(msg_id, '(RFC822)')
        if status != 'OK':
            return
        
        # 解析邮件
        email_message = email.message_from_bytes(msg_data[0][1])
        
        # 获取邮件头信息
        subject = self.decode_email_header(email_message.get('Subject', ''))
        sender = self.decode_email_header(email_message.get('From', ''))
        date = email_message.get('Date', '')
        
        # 获取邮件正文
        body = self.get_email_body(email_message)
        
        # 应用过滤器
        if sender_filter and sender_filter not in sender:
            return
        
        if subject_filter and subject_filter not in subject:
            return
        
        # 检查关键词
        content_to_check = f"{subject} {body}".lower()
        matched_keywords = []
        
        for keyword in keywords:
            if keyword.lower() in content_to_check:
                matched_keywords.append(keyword)
        
        if matched_keywords:
            # 创建邮件告警记录
            email_alert = {
                'timestamp': datetime.now().isoformat(),
                'account': account.get('name', 'Unknown'),
                'sender': sender,
                'subject': subject,
                'body': body[:500] + '...' if len(body) > 500 else body,  # 限制长度
                'matched_keywords': matched_keywords,
                'date': date
            }
            
            email_logs.append(email_alert)
            
            # 限制邮件日志数量
            if len(email_logs) > CONFIG.get('max_logs', 10000):
                email_logs.pop(0)
            
            # 发送告警
            self.send_email_alert(email_alert)
            STATS['email_alerts'] += 1
            
            self._log_service(f"邮件告警: {account.get('name')} - {subject}")
    
    def decode_email_header(self, header):
        """解码邮件头"""
        if not header:
            return ''
        
        decoded_parts = decode_header(header)
        decoded_string = ''
        
        for part, encoding in decoded_parts:
            if isinstance(part, bytes):
                if encoding:
                    decoded_string += part.decode(encoding)
                else:
                    decoded_string += part.decode('utf-8', errors='ignore')
            else:
                decoded_string += part
        
        return decoded_string
    
    def get_email_body(self, email_message):
        """获取邮件正文"""
        body = ''
        
        if email_message.is_multipart():
            for part in email_message.walk():
                content_type = part.get_content_type()
                if content_type == 'text/plain':
                    charset = part.get_content_charset() or 'utf-8'
                    body += part.get_payload(decode=True).decode(charset, errors='ignore')
                elif content_type == 'text/html' and not body:
                    # 如果没有纯文本，使用HTML（简单处理）
                    charset = part.get_content_charset() or 'utf-8'
                    html_body = part.get_payload(decode=True).decode(charset, errors='ignore')
                    # 简单去除HTML标签
                    import re
                    body = re.sub(r'<[^>]+>', '', html_body)
        else:
            charset = email_message.get_content_charset() or 'utf-8'
            body = email_message.get_payload(decode=True).decode(charset, errors='ignore')
        
        return body.strip()
    
    def send_email_alert(self, email_alert):
        """发送邮件告警到配置的通知渠道"""
        alert_data = {
            'type': 'email',
            'source': f"邮箱告警 - {email_alert['account']}",
            'message': f"发件人: {email_alert['sender']}\n主题: {email_alert['subject']}\n内容: {email_alert['body']}",
            'timestamp': email_alert['timestamp'],
            'keywords': email_alert['matched_keywords']
        }
        
        # 发送到各个通知渠道
        if CONFIG.get('dingtalk_enabled'):
            self._send_dingtalk_alert(alert_data)
        
        if CONFIG.get('wechat_enabled'):
            self._send_wechat_alert(alert_data)
        
        if CONFIG.get('feishu_enabled'):
            self._send_feishu_alert(alert_data)
        
        if CONFIG.get('sms_enabled'):
            self._send_sms_alert(alert_data)
    
    def _send_dingtalk_alert(self, alert_data):
        """发送钉钉告警"""
        try:
            webhook = CONFIG.get('dingtalk_webhook')
            if not webhook:
                return
            
            message = {
                'msgtype': 'text',
                'text': {
                    'content': f"📧 {alert_data['source']}\n\n{alert_data['message']}\n\n匹配关键词: {', '.join(alert_data['keywords'])}\n时间: {alert_data['timestamp']}"
                }
            }
            
            response = requests.post(webhook, json=message, timeout=10)
            if response.status_code == 200:
                STATS['sent_alerts'] += 1
            else:
                STATS['failed_alerts'] += 1
                
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"钉钉邮件告警发送失败: {str(e)}")
    
    def _send_wechat_alert(self, alert_data):
        """发送企业微信告警"""
        try:
            webhook = CONFIG.get('wechat_webhook')
            if not webhook:
                return
            
            message = {
                'msgtype': 'text',
                'text': {
                    'content': f"📧 {alert_data['source']}\n\n{alert_data['message']}\n\n匹配关键词: {', '.join(alert_data['keywords'])}\n时间: {alert_data['timestamp']}"
                }
            }
            
            response = requests.post(webhook, json=message, timeout=10)
            if response.status_code == 200:
                STATS['sent_alerts'] += 1
            else:
                STATS['failed_alerts'] += 1
                
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"企业微信邮件告警发送失败: {str(e)}")
    
    def _send_feishu_alert(self, alert_data):
        """发送飞书告警"""
        try:
            import hashlib
            import hmac
            import base64
            
            message = f"📧 邮件告警\n" \
                     f"时间: {alert_data['timestamp']}\n" \
                     f"来源: {alert_data['source']}\n" \
                     f"内容: {alert_data['message']}"
            
            payload = {
                "msg_type": "text",
                "content": {
                    "text": message
                }
            }
            
            # 如果配置了@用户
            if CONFIG['feishu_at_users']:
                at_users = [user.strip() for user in CONFIG['feishu_at_users'].split(',') if user.strip()]
                if at_users:
                    payload["content"]["at"] = {
                        "atMobiles": at_users,
                        "isAtAll": False
                    }
            
            headers = {'Content-Type': 'application/json'}
            
            # 如果配置了签名密钥
            if CONFIG['feishu_secret']:
                timestamp = str(int(time.time()))
                string_to_sign = f"{timestamp}\n{CONFIG['feishu_secret']}"
                hmac_code = hmac.new(
                    string_to_sign.encode("utf-8"),
                    digestmod=hashlib.sha256
                ).digest()
                sign = base64.b64encode(hmac_code).decode('utf-8')
                
                payload["timestamp"] = timestamp
                payload["sign"] = sign
            
            response = requests.post(CONFIG['feishu_webhook'], json=payload, headers=headers, timeout=10)
            if response.status_code == 200:
                result = response.json()
                if result.get('StatusCode') == 0:
                    STATS['sent_alerts'] += 1
                    self._log_service("飞书邮件告警发送成功")
                else:
                    STATS['failed_alerts'] += 1
                    self._log_service(f"飞书邮件告警发送失败: {result.get('msg', '未知错误')}")
            else:
                STATS['failed_alerts'] += 1
                self._log_service(f"飞书邮件告警发送失败: {response.status_code}")
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"飞书邮件告警发送异常: {str(e)}")
    
    def _send_sms_alert(self, alert_data):
        """发送短信告警"""
        try:
            access_key = CONFIG.get('aliyun_access_key')
            access_secret = CONFIG.get('aliyun_access_secret')
            sign_name = CONFIG.get('aliyun_sign_name')
            template_code = CONFIG.get('aliyun_template_code')
            phone_numbers = CONFIG.get('phone_numbers', [])
            
            if not all([access_key, access_secret, sign_name, template_code]) or not phone_numbers:
                return
            
            # 构建短信内容
            sms_content = f"{alert_data['source']}: {alert_data['message'][:100]}..."
            
            config = open_api_models.Config(
                access_key_id=access_key,
                access_key_secret=access_secret
            )
            config.endpoint = 'dysmsapi.aliyuncs.com'
            
            client = Dysmsapi20170525Client(config)
            
            for phone in phone_numbers:
                request = dysmsapi_20170525_models.SendSmsRequest(
                    phone_numbers=phone,
                    sign_name=sign_name,
                    template_code=template_code,
                    template_param=json.dumps({'content': sms_content})
                )
                
                response = client.send_sms(request)
                if response.body.code == 'OK':
                    STATS['sent_alerts'] += 1
                else:
                    STATS['failed_alerts'] += 1
                    
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"短信邮件告警发送失败: {str(e)}")
    
    def _log_service(self, message):
        """记录服务日志"""
        global service_logs
        log_entry = {
            'timestamp': datetime.now().isoformat(),
            'message': message
        }
        service_logs.append(log_entry)
        
        # 限制日志数量
        if len(service_logs) > 1000:
            service_logs.pop(0)
        
        print(f"[{datetime.now().strftime('%H:%M:%S')}] {message}")

class SyslogServer:
    def __init__(self, port=514):
        self.port = port
        self.socket = None
        self.running = False
        self.thread = None
        
    def start(self):
        if self.running:
            self._log_service("Syslog服务器已在运行中")
            return True
            
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.socket.bind(('0.0.0.0', self.port))
            self.running = True
            self.thread = threading.Thread(target=self._listen)
            self.thread.daemon = True
            self.thread.start()
            self._log_service(f"Syslog服务器启动成功，监听端口: {self.port}")
            return True
        except Exception as e:
            self.running = False
            if self.socket:
                self.socket.close()
                self.socket = None
            self._log_service(f"Syslog服务器启动失败: {str(e)}")
            return False
    
    def stop(self):
        self.running = False
        if self.socket:
            self.socket.close()
        self._log_service("Syslog服务器已停止")
    
    def _listen(self):
        while self.running:
            try:
                data, addr = self.socket.recvfrom(1024)
                message = data.decode('utf-8', errors='ignore')
                self._process_message(message, addr)
            except Exception as e:
                if self.running:
                    self._log_service(f"接收消息错误: {str(e)}")
    
    def _process_message(self, message, addr):
        global STATS, logs_buffer
        
        log_entry = {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'source': f"{addr[0]}:{addr[1]}",
            'message': message.strip(),
            'raw': message
        }
        
        # 添加到日志缓冲区
        logs_buffer.append(log_entry)
        if len(logs_buffer) > CONFIG['max_logs']:
            logs_buffer.pop(0)
        
        STATS['received_logs'] += 1
        
        # 检查是否需要告警
        if self._should_alert(message):
            self._send_alert(log_entry)
    
    def _should_alert(self, message):
        message_lower = message.lower()
        return any(keyword in message_lower for keyword in CONFIG['alert_keywords'])
    
    def _send_alert(self, log_entry):
        alert_data = {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'log_entry': log_entry,
            'alert_type': 'keyword_match'
        }
        
        # 发送到钉钉
        if CONFIG['dingtalk_enabled'] and CONFIG['dingtalk_webhook']:
            self._send_dingtalk_alert(alert_data)
        
        # 发送到企业微信
        if CONFIG['wechat_enabled'] and CONFIG['wechat_webhook']:
            self._send_wechat_alert(alert_data)
        
        # 发送到飞书
        if CONFIG['feishu_enabled'] and CONFIG['feishu_webhook']:
            self._send_feishu_alert(alert_data)
        
        # 发送短信
        if CONFIG['sms_enabled'] and CONFIG['aliyun_access_key'] and CONFIG['phone_numbers']:
            self._send_sms_alert(alert_data)
        
        # 记录告警
        alerts_buffer.append(alert_data)
        if len(alerts_buffer) > CONFIG['max_logs']:
            alerts_buffer.pop(0)
    
    def _send_dingtalk_alert(self, alert_data):
        try:
            message = f"🚨 系统告警\n" \
                     f"时间: {alert_data['timestamp']}\n" \
                     f"来源: {alert_data['log_entry']['source']}\n" \
                     f"内容: {alert_data['log_entry']['message']}"
            
            payload = {
                "msgtype": "text",
                "text": {
                    "content": message
                }
            }
            
            response = requests.post(CONFIG['dingtalk_webhook'], json=payload, timeout=10)
            if response.status_code == 200:
                STATS['sent_alerts'] += 1
                self._log_service("钉钉告警发送成功")
            else:
                STATS['failed_alerts'] += 1
                self._log_service(f"钉钉告警发送失败: {response.status_code}")
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"钉钉告警发送异常: {str(e)}")
    
    def _send_wechat_alert(self, alert_data):
        try:
            message = f"🚨 系统告警\n" \
                     f"时间: {alert_data['timestamp']}\n" \
                     f"来源: {alert_data['log_entry']['source']}\n" \
                     f"内容: {alert_data['log_entry']['message']}"
            
            payload = {
                "msgtype": "text",
                "text": {
                    "content": message
                }
            }
            
            response = requests.post(CONFIG['wechat_webhook'], json=payload, timeout=10)
            if response.status_code == 200:
                STATS['sent_alerts'] += 1
                self._log_service("企业微信告警发送成功")
            else:
                STATS['failed_alerts'] += 1
                self._log_service(f"企业微信告警发送失败: {response.status_code}")
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"企业微信告警发送异常: {str(e)}")
    
    def _send_feishu_alert(self, alert_data):
        try:
            import hashlib
            import hmac
            import base64
            
            message = f"🚨 系统告警\n" \
                     f"时间: {alert_data['timestamp']}\n" \
                     f"来源: {alert_data['log_entry']['source']}\n" \
                     f"内容: {alert_data['log_entry']['message']}"
            
            payload = {
                "msg_type": "text",
                "content": {
                    "text": message
                }
            }
            
            # 如果配置了@用户
            if CONFIG['feishu_at_users']:
                at_users = [user.strip() for user in CONFIG['feishu_at_users'].split(',') if user.strip()]
                if at_users:
                    payload["content"]["at"] = {
                        "atMobiles": at_users,
                        "isAtAll": False
                    }
            
            headers = {'Content-Type': 'application/json'}
            
            # 如果配置了签名密钥
            if CONFIG['feishu_secret']:
                timestamp = str(int(time.time()))
                string_to_sign = f"{timestamp}\n{CONFIG['feishu_secret']}"
                hmac_code = hmac.new(
                    string_to_sign.encode("utf-8"),
                    digestmod=hashlib.sha256
                ).digest()
                sign = base64.b64encode(hmac_code).decode('utf-8')
                
                payload["timestamp"] = timestamp
                payload["sign"] = sign
            
            response = requests.post(CONFIG['feishu_webhook'], json=payload, headers=headers, timeout=10)
            if response.status_code == 200:
                result = response.json()
                if result.get('StatusCode') == 0:
                    STATS['sent_alerts'] += 1
                    self._log_service("飞书告警发送成功")
                else:
                    STATS['failed_alerts'] += 1
                    self._log_service(f"飞书告警发送失败: {result.get('msg', '未知错误')}")
            else:
                STATS['failed_alerts'] += 1
                self._log_service(f"飞书告警发送失败: {response.status_code}")
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"飞书告警发送异常: {str(e)}")
    
    def _send_sms_alert(self, alert_data):
        try:
            config = open_api_models.Config(
                access_key_id=CONFIG['aliyun_access_key'],
                access_key_secret=CONFIG['aliyun_access_secret']
            )
            config.endpoint = 'dysmsapi.aliyuncs.com'
            client = Dysmsapi20170525Client(config)
            
            message = f"系统告警: {alert_data['log_entry']['message'][:50]}"
            
            for phone in CONFIG['phone_numbers']:
                send_sms_request = dysmsapi_20170525_models.SendSmsRequest(
                    phone_numbers=phone,
                    sign_name=CONFIG['aliyun_sign_name'],
                    template_code=CONFIG['aliyun_template_code'],
                    template_param=json.dumps({"content": message})
                )
                
                response = client.send_sms(send_sms_request)
                if response.body.code == 'OK':
                    STATS['sent_alerts'] += 1
                    self._log_service(f"短信告警发送成功: {phone}")
                else:
                    STATS['failed_alerts'] += 1
                    self._log_service(f"短信告警发送失败: {phone}, {response.body.message}")
        except Exception as e:
            STATS['failed_alerts'] += 1
            self._log_service(f"短信告警发送异常: {str(e)}")
    
    def _log_service(self, message):
        global service_logs
        log_entry = {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'message': message
        }
        service_logs.append(log_entry)
        if len(service_logs) > CONFIG['max_logs']:
            service_logs.pop(0)
        print(f"[{log_entry['timestamp']}] {message}")

# 加载配置
load_config()

# 创建全局实例
syslog_server = SyslogServer(CONFIG['syslog_port'])
email_collector = EmailCollector()

# Web路由
@app.route('/')
def index():
    return render_template('index.html')

@app.route('/favicon.svg')
def favicon():
    from flask import send_file
    return send_file('templates/favicon.svg', mimetype='image/svg+xml')

@app.route('/api/logs')
def get_logs():
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    
    total = len(logs_buffer)
    start_idx = (page - 1) * per_page
    end_idx = start_idx + per_page
    
    # 从最新的日志开始分页
    reversed_logs = list(reversed(logs_buffer))
    page_logs = reversed_logs[start_idx:end_idx]
    
    return jsonify({
        'logs': page_logs,
        'total': total,
        'page': page,
        'per_page': per_page,
        'total_pages': (total + per_page - 1) // per_page if total > 0 else 1
    })

@app.route('/api/alerts')
def get_alerts():
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 20, type=int)
    
    total = len(alerts_buffer)
    start_idx = (page - 1) * per_page
    end_idx = start_idx + per_page
    
    # 从最新的告警开始分页
    reversed_alerts = list(reversed(alerts_buffer))
    page_alerts = reversed_alerts[start_idx:end_idx]
    
    return jsonify({
        'alerts': page_alerts,
        'total': total,
        'page': page,
        'per_page': per_page,
        'total_pages': (total + per_page - 1) // per_page if total > 0 else 1
    })

@app.route('/api/service_logs')
def get_service_logs():
    return jsonify({
        'logs': service_logs[-100:],  # 最近100条
        'total': len(service_logs)
    })

@app.route('/api/stats')
def get_stats():
    uptime = datetime.now() - STATS['start_time']
    uptime_str = str(uptime).split('.')[0]  # 去掉微秒
    
    return jsonify({
        'received_logs': STATS['received_logs'],
        'sent_alerts': STATS['sent_alerts'],
        'failed_alerts': STATS['failed_alerts'],
        'checked_emails': STATS['checked_emails'],
        'email_alerts': STATS['email_alerts'],
        'uptime': uptime_str,
        'server_status': 'running' if syslog_server.running else 'stopped',
        'server_port': CONFIG['syslog_port']
    })

@app.route('/api/ip_stats')
def get_ip_stats():
    page = int(request.args.get('page', 1))
    page_size = 10  # 固定每页10条
    
    # 统计各IP的日志数量
    ip_counts = {}
    for log in logs_buffer:
        source = log.get('source', 'unknown')
        # 提取IP地址部分，去掉端口号
        if ':' in source:
            source_ip = source.split(':')[0]
        else:
            source_ip = source
        ip_counts[source_ip] = ip_counts.get(source_ip, 0) + 1
    
    # 按数量排序
    sorted_ips = sorted(ip_counts.items(), key=lambda x: x[1], reverse=True)
    
    # 计算总数和百分比
    total_logs = sum(ip_counts.values())
    
    # 分页处理
    total_items = len(sorted_ips)
    total_pages = (total_items + page_size - 1) // page_size if total_items > 0 else 1
    start_idx = (page - 1) * page_size
    end_idx = start_idx + page_size
    page_data = sorted_ips[start_idx:end_idx]
    
    # 构建返回数据
    ip_stats = []
    for i, (ip, count) in enumerate(page_data):
        rank = start_idx + i + 1
        percentage = (count / total_logs * 100) if total_logs > 0 else 0
        ip_stats.append({
            'rank': rank,
            'ip': ip,
            'count': count,
            'percentage': round(percentage, 2)
        })
    
    return jsonify({
        'ip_stats': ip_stats,
        'current_page': page,
        'total_pages': total_pages,
        'total_items': total_items,
        'page_size': page_size
    })

@app.route('/api/top_ip_stats')
def get_top_ip_stats():
    # 统计各IP的日志数量
    ip_counts = {}
    for log in logs_buffer:
        source = log.get('source', 'unknown')
        # 提取IP地址部分，去掉端口号
        if ':' in source:
            source_ip = source.split(':')[0]
        else:
            source_ip = source
        ip_counts[source_ip] = ip_counts.get(source_ip, 0) + 1
    
    # 按数量排序，取前10个
    sorted_ips = sorted(ip_counts.items(), key=lambda x: x[1], reverse=True)[:10]
    
    # 计算总数
    total_logs = sum(ip_counts.values())
    
    # 构建返回数据
    top_ip_stats = []
    for i, (ip, count) in enumerate(sorted_ips, 1):
        percentage = (count / total_logs * 100) if total_logs > 0 else 0
        top_ip_stats.append({
            'rank': i,
            'ip': ip,
            'count': count,
            'percentage': round(percentage, 1)
        })
    
    return jsonify({
        'top_ip_stats': top_ip_stats,
        'total_ips': len(ip_counts),
        'total_logs': total_logs
    })

@app.route('/api/config', methods=['GET', 'POST'])
def handle_config():
    if request.method == 'GET':
        return jsonify(CONFIG)
    else:
        data = request.json
        CONFIG.update(data)
        # 保存配置到文件
        save_config()
        return jsonify({'status': 'success'})

@app.route('/api/test_alert', methods=['POST'])
def test_alert():
    test_log = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'source': 'test:0',
        'message': 'This is a test alert message with error keyword',
        'raw': 'Test alert'
    }
    
    syslog_server._send_alert(test_log)
    return jsonify({'status': 'success', 'message': '测试告警已发送'})

@app.route('/api/test_message', methods=['POST'])
def test_message():
    data = request.get_json()
    message = data.get('message', '')
    
    if not message:
        return jsonify({'status': 'error', 'message': '消息内容不能为空'})
    
    # 模拟接收到的syslog消息
    test_log = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'source': 'test:manual',
        'message': message,
        'raw': f'<14>1 {datetime.now().isoformat()} test manual - - - {message}'
    }
    
    # 添加到日志缓冲区
    logs_buffer.append(test_log)
    if len(logs_buffer) > CONFIG['max_logs']:
        logs_buffer.pop(0)
    
    STATS['received_logs'] += 1
    
    # 检查是否需要发送告警
    if syslog_server._should_alert(message):
        syslog_server._send_alert(test_log)
        return jsonify({'status': 'success', 'message': f'测试消息已发送，触发告警推送'})
    else:
        return jsonify({'status': 'success', 'message': '测试消息已发送，未触发告警'})


@app.route('/api/server/start', methods=['POST'])
def start_server():
    global syslog_server
    # 停止当前服务器
    syslog_server.stop()
    # 使用新配置重新创建服务器实例
    syslog_server = SyslogServer(CONFIG['syslog_port'])
    if syslog_server.start():
        return jsonify({'status': 'success', 'message': f'Syslog服务器启动成功，监听端口: {CONFIG["syslog_port"]}'})
    else:
        return jsonify({'status': 'error', 'message': 'Syslog服务器启动失败'})

@app.route('/api/server/stop', methods=['POST'])
def stop_server():
    syslog_server.stop()
    return jsonify({'status': 'success', 'message': 'Syslog服务器已停止'})

@app.route('/api/logs/clear', methods=['POST'])
def clear_logs():
    global logs_buffer
    logs_buffer.clear()
    syslog_server._log_service("日志已清空")
    return jsonify({'status': 'success', 'message': '日志已清空'})

@app.route('/api/alerts/clear', methods=['POST'])
def clear_alerts():
    global alerts_buffer
    alerts_buffer.clear()
    syslog_server._log_service("告警记录已清空")
    return jsonify({'status': 'success', 'message': '告警记录已清空'})

@app.route('/api/notification/test/dingtalk', methods=['POST'])
def test_dingtalk():
    if not CONFIG['dingtalk_enabled'] or not CONFIG['dingtalk_webhook']:
        return jsonify({'status': 'error', 'message': '钉钉未启用或未配置'})
    
    test_alert = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'log_entry': {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'source': 'test:0',
            'message': '这是一条钉钉推送测试消息'
        },
        'alert_type': 'test'
    }
    
    syslog_server._send_dingtalk_alert(test_alert)
    return jsonify({'status': 'success', 'message': '钉钉测试消息已发送'})

@app.route('/api/notification/test/wechat', methods=['POST'])
def test_wechat():
    if not CONFIG['wechat_enabled'] or not CONFIG['wechat_webhook']:
        return jsonify({'status': 'error', 'message': '企业微信未启用或未配置'})
    
    test_alert = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'log_entry': {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'source': 'test:0',
            'message': '这是一条企业微信推送测试消息'
        },
        'alert_type': 'test'
    }
    
    syslog_server._send_wechat_alert(test_alert)
    return jsonify({'status': 'success', 'message': '企业微信测试消息已发送'})

@app.route('/api/notification/test/feishu', methods=['POST'])
def test_feishu():
    if not CONFIG['feishu_enabled'] or not CONFIG['feishu_webhook']:
        return jsonify({'status': 'error', 'message': '飞书未启用或未配置'})
    
    test_alert = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'log_entry': {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'source': 'test:0',
            'message': '这是一条飞书推送测试消息'
        },
        'alert_type': 'test'
    }
    
    syslog_server._send_feishu_alert(test_alert)
    return jsonify({'status': 'success', 'message': '飞书测试消息已发送'})

@app.route('/api/notification/test/sms', methods=['POST'])
def test_sms():
    if not CONFIG['sms_enabled'] or not CONFIG['aliyun_access_key'] or not CONFIG['phone_numbers']:
        return jsonify({'status': 'error', 'message': '短信未启用或未配置'})
    
    test_alert = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'log_entry': {
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'source': 'test:0',
            'message': '这是一条短信推送测试消息'
        },
        'alert_type': 'test'
    }
    
    syslog_server._send_sms_alert(test_alert)
    return jsonify({'status': 'success', 'message': '短信测试消息已发送'})

# 邮件相关API
@app.route('/api/emails')
def get_emails():
    """获取邮件日志"""
    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 20))
    
    start_idx = (page - 1) * per_page
    end_idx = start_idx + per_page
    
    # 返回最新的邮件日志
    emails = list(reversed(email_logs))[start_idx:end_idx]
    
    return jsonify({
        'emails': emails,
        'total': len(email_logs),
        'page': page,
        'per_page': per_page
    })

@app.route('/api/email/config', methods=['GET', 'POST'])
def handle_email_config():
    """处理邮件配置"""
    if request.method == 'GET':
        return jsonify({
            'email_enabled': CONFIG.get('email_enabled', False),
            'email_check_interval': CONFIG.get('email_check_interval', 60),
            'email_accounts': CONFIG.get('email_accounts', [])
        })
    
    elif request.method == 'POST':
        data = request.get_json()
        
        # 更新邮件配置
        CONFIG['email_enabled'] = data.get('email_enabled', False)
        CONFIG['email_check_interval'] = data.get('email_check_interval', 60)
        CONFIG['email_accounts'] = data.get('email_accounts', [])
        
        # 保存配置
        save_config()
        
        # 重启邮件采集服务
        email_collector.stop()
        if CONFIG.get('email_enabled', False):
            email_collector.start()
        
        return jsonify({'status': 'success', 'message': '邮件配置已保存'})

@app.route('/api/email/service/start', methods=['POST'])
def start_email_service():
    """启动邮件采集服务"""
    if email_collector.start():
        return jsonify({'status': 'success', 'message': '邮件采集服务启动成功'})
    else:
        return jsonify({'status': 'error', 'message': '邮件采集服务启动失败'})

@app.route('/api/email/service/stop', methods=['POST'])
def stop_email_service():
    """停止邮件采集服务"""
    email_collector.stop()
    return jsonify({'status': 'success', 'message': '邮件采集服务已停止'})

@app.route('/api/email/test', methods=['POST'])
def test_email_account():
    """测试邮箱连接"""
    data = request.get_json()
    
    server = data.get('server')
    port = data.get('port', 993)
    use_ssl = data.get('use_ssl', True)
    username = data.get('username')
    password = data.get('password')
    
    if not all([server, username, password]):
        return jsonify({'status': 'error', 'message': '邮箱配置不完整'})
    
    try:
        # 测试连接
        if use_ssl:
            mail = imaplib.IMAP4_SSL(server, port)
        else:
            mail = imaplib.IMAP4(server, port)
        
        mail.login(username, password)
        mail.select('INBOX')
        
        # 获取邮箱信息
        status, messages = mail.search(None, 'ALL')
        total_emails = len(messages[0].split()) if status == 'OK' else 0
        
        mail.close()
        mail.logout()
        
        return jsonify({
            'status': 'success', 
            'message': f'邮箱连接成功，共有 {total_emails} 封邮件',
            'total_emails': total_emails
        })
        
    except Exception as e:
        return jsonify({'status': 'error', 'message': f'邮箱连接失败: {str(e)}'})

@app.route('/api/emails/clear', methods=['POST'])
def clear_emails():
    """清空邮件日志"""
    global email_logs
    email_logs.clear()
    return jsonify({'status': 'success', 'message': '邮件日志已清空'})

# Webhook相关API
@app.route('/api/webhook/config', methods=['GET', 'POST'])
def handle_webhook_config():
    """处理Webhook配置"""
    if request.method == 'GET':
        return jsonify({
            'status': 'success',
            'config': {
                'webhook_enabled': CONFIG.get('webhook_enabled', False),
                'webhook_path': CONFIG.get('webhook_path', '/webhook/alert'),
                'webhook_token': CONFIG.get('webhook_token', '')
            }
        })
    
    elif request.method == 'POST':
        try:
            data = request.get_json()
            CONFIG['webhook_enabled'] = data.get('webhook_enabled', False)
            CONFIG['webhook_path'] = data.get('webhook_path', '/webhook/alert')
            CONFIG['webhook_token'] = data.get('webhook_token', '')
            
            # 保存配置到文件
            with open('config.json', 'w', encoding='utf-8') as f:
                json.dump(CONFIG, f, ensure_ascii=False, indent=2)
            
            return jsonify({'status': 'success', 'message': 'Webhook配置已保存'})
        except Exception as e:
            return jsonify({'status': 'error', 'message': f'保存配置失败: {str(e)}'})

@app.route('/api/webhook/logs', methods=['GET', 'DELETE'])
def handle_webhook_logs():
    """处理Webhook日志"""
    global webhook_logs
    
    if request.method == 'GET':
        return jsonify({
            'status': 'success',
            'logs': webhook_logs[-100:],  # 返回最新100条
            'total': len(webhook_logs)
        })
    
    elif request.method == 'DELETE':
        webhook_logs.clear()
        return jsonify({'status': 'success', 'message': 'Webhook日志已清空'})

@app.route('/webhook/alert', methods=['POST'])
def webhook_alert():
    """Webhook告警接收端点"""
    try:
        # 检查是否启用Webhook
        if not CONFIG.get('webhook_enabled', False):
            return jsonify({'status': 'error', 'message': 'Webhook功能未启用'}), 403
        
        # 验证Token（如果设置了）
        webhook_token = CONFIG.get('webhook_token', '')
        if webhook_token:
            auth_header = request.headers.get('Authorization', '')
            if not auth_header.startswith('Bearer ') or auth_header[7:] != webhook_token:
                _log_webhook('认证失败', 'error', '无效的认证Token')
                return jsonify({'status': 'error', 'message': '认证失败'}), 401
        
        # 解析请求数据
        data = request.get_json()
        if not data:
            _log_webhook('数据解析失败', 'error', '请求体不是有效的JSON格式')
            return jsonify({'status': 'error', 'message': '请求体必须是JSON格式'}), 400
        
        # 验证必需字段
        required_fields = ['title', 'message']
        for field in required_fields:
            if field not in data:
                _log_webhook('字段验证失败', 'error', f'缺少必需字段: {field}')
                return jsonify({'status': 'error', 'message': f'缺少必需字段: {field}'}), 400
        
        # 构建告警数据
        alert_data = {
            'timestamp': data.get('timestamp', datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
            'source': data.get('source', 'webhook'),
            'message': f"{data['title']}: {data['message']}",
            'level': data.get('level', 'info'),
            'channels': []
        }
        
        # 发送到各个通知渠道
        success_channels = []
        failed_channels = []
        
        # 钉钉通知
        if CONFIG.get('dingtalk_enabled', False):
            try:
                _send_dingtalk_webhook_alert(alert_data)
                success_channels.append('钉钉')
                alert_data['channels'].append('钉钉')
            except Exception as e:
                failed_channels.append(f'钉钉: {str(e)}')
        
        # 企业微信通知
        if CONFIG.get('wechat_enabled', False):
            try:
                _send_wechat_webhook_alert(alert_data)
                success_channels.append('企业微信')
                alert_data['channels'].append('企业微信')
            except Exception as e:
                failed_channels.append(f'企业微信: {str(e)}')
        
        # 飞书通知
        if CONFIG.get('feishu_enabled', False):
            try:
                _send_feishu_webhook_alert(alert_data)
                success_channels.append('飞书')
                alert_data['channels'].append('飞书')
            except Exception as e:
                failed_channels.append(f'飞书: {str(e)}')
        
        # 短信通知
        if CONFIG.get('sms_enabled', False):
            try:
                _send_sms_webhook_alert(alert_data)
                success_channels.append('短信')
                alert_data['channels'].append('短信')
            except Exception as e:
                failed_channels.append(f'短信: {str(e)}')
        
        # 记录到告警缓冲区
        alerts_buffer.append(alert_data)
        if len(alerts_buffer) > CONFIG['max_logs']:
            alerts_buffer.pop(0)
        
        # 记录Webhook日志
        channels_info = f"成功: {', '.join(success_channels) if success_channels else '无'}"
        if failed_channels:
            channels_info += f" | 失败: {', '.join(failed_channels)}"
        
        _log_webhook('告警接收成功', 'info', f"标题: {data['title']} | 渠道: {channels_info}")
        
        return jsonify({
            'status': 'success',
            'message': '告警已接收并处理',
            'channels': {
                'success': success_channels,
                'failed': failed_channels
            }
        })
        
    except Exception as e:
        _log_webhook('处理失败', 'error', f'异常: {str(e)}')
        return jsonify({'status': 'error', 'message': f'处理失败: {str(e)}'}), 500

def _log_webhook(title, level, message):
    """记录Webhook日志"""
    global webhook_logs
    log_entry = {
        'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        'level': level,
        'message': f"{title}: {message}"
    }
    webhook_logs.append(log_entry)
    if len(webhook_logs) > 1000:  # 限制日志数量
        webhook_logs.pop(0)

def _send_dingtalk_webhook_alert(alert_data):
    """发送钉钉Webhook告警"""
    webhook_url = CONFIG.get('dingtalk_webhook', '')
    if not webhook_url:
        raise Exception('钉钉Webhook URL未配置')
    
    message = {
        "msgtype": "text",
        "text": {
            "content": f"🚨 Webhook告警\n时间: {alert_data['timestamp']}\n来源: {alert_data['source']}\n内容: {alert_data['message']}"
        }
    }
    
    response = requests.post(webhook_url, json=message, timeout=10)
    if response.status_code != 200:
        raise Exception(f'HTTP {response.status_code}')

def _send_wechat_webhook_alert(alert_data):
    """发送企业微信Webhook告警"""
    webhook_url = CONFIG.get('wechat_webhook', '')
    if not webhook_url:
        raise Exception('企业微信Webhook URL未配置')
    
    message = {
        "msgtype": "text",
        "text": {
            "content": f"🚨 Webhook告警\n时间: {alert_data['timestamp']}\n来源: {alert_data['source']}\n内容: {alert_data['message']}"
        }
    }
    
    response = requests.post(webhook_url, json=message, timeout=10)
    if response.status_code != 200:
        raise Exception(f'HTTP {response.status_code}')

def _send_feishu_webhook_alert(alert_data):
    """发送飞书Webhook告警"""
    try:
        import hashlib
        import hmac
        import base64
        
        message = f"🔔 Webhook告警\n" \
                 f"时间: {alert_data['timestamp']}\n" \
                 f"来源: {alert_data['source']}\n" \
                 f"级别: {alert_data['level']}\n" \
                 f"内容: {alert_data['message']}"
        
        payload = {
            "msg_type": "text",
            "content": {
                "text": message
            }
        }
        
        # 如果配置了@用户
        if CONFIG['feishu_at_users']:
            at_users = [user.strip() for user in CONFIG['feishu_at_users'].split(',') if user.strip()]
            if at_users:
                payload["content"]["at"] = {
                    "atMobiles": at_users,
                    "isAtAll": False
                }
        
        headers = {'Content-Type': 'application/json'}
        
        # 如果配置了签名密钥
        if CONFIG['feishu_secret']:
            timestamp = str(int(time.time()))
            string_to_sign = f"{timestamp}\n{CONFIG['feishu_secret']}"
            hmac_code = hmac.new(
                string_to_sign.encode("utf-8"),
                digestmod=hashlib.sha256
            ).digest()
            sign = base64.b64encode(hmac_code).decode('utf-8')
            
            payload["timestamp"] = timestamp
            payload["sign"] = sign
        
        response = requests.post(CONFIG['feishu_webhook'], json=payload, headers=headers, timeout=10)
        if response.status_code == 200:
            result = response.json()
            if result.get('StatusCode') == 0:
                STATS['sent_alerts'] += 1
                _log_webhook('飞书告警发送成功', 'info', f"消息: {alert_data['message']}")
            else:
                STATS['failed_alerts'] += 1
                _log_webhook('飞书告警发送失败', 'error', f"错误: {result.get('msg', '未知错误')}")
        else:
            STATS['failed_alerts'] += 1
            _log_webhook('飞书告警发送失败', 'error', f"HTTP状态码: {response.status_code}")
    except Exception as e:
        STATS['failed_alerts'] += 1
        _log_webhook('飞书告警发送异常', 'error', f"异常: {str(e)}")

def _send_sms_webhook_alert(alert_data):
    """发送短信Webhook告警"""
    access_key = CONFIG.get('aliyun_access_key', '')
    access_secret = CONFIG.get('aliyun_access_secret', '')
    sign_name = CONFIG.get('aliyun_sign_name', '')
    template_code = CONFIG.get('aliyun_template_code', '')
    phone_numbers = CONFIG.get('phone_numbers', [])
    
    if not all([access_key, access_secret, sign_name, template_code, phone_numbers]):
        raise Exception('短信配置不完整')
    
    config = open_api_models.Config(
        access_key_id=access_key,
        access_key_secret=access_secret
    )
    config.endpoint = 'dysmsapi.aliyuncs.com'
    
    client = Dysmsapi20170525Client(config)
    
    for phone in phone_numbers:
        request_sms = dysmsapi_20170525_models.SendSmsRequest(
            phone_numbers=phone,
            sign_name=sign_name,
            template_code=template_code,
            template_param=json.dumps({
                'content': alert_data['message'][:50]  # 限制长度
            })
        )
        
        response = client.send_sms(request_sms)
        if response.body.code != 'OK':
            raise Exception(f'短信发送失败: {response.body.message}')

def create_tray_icon():
    """创建系统托盘图标"""
    if not TRAY_AVAILABLE:
        return None
    
    # 创建一个简单的图标
    image = Image.new('RGB', (64, 64), color='blue')
    draw = ImageDraw.Draw(image)
    draw.ellipse([16, 16, 48, 48], fill='lightblue')
    draw.text((20, 25), 'SL', fill='white')
    
    return image

def on_start_service(icon, item):
    """启动服务"""
    global service_running
    if not service_running:
        start_services()
        service_running = True
        print("服务已启动")

def on_stop_service(icon, item):
    """停止服务"""
    global service_running
    if service_running:
        stop_services()
        service_running = False
        print("服务已停止")

def on_open_web(icon, item):
    """打开Web界面"""
    webbrowser.open(f'http://localhost:{CONFIG["web_port"]}')

def on_quit(icon, item):
    """退出程序"""
    global service_running
    if service_running:
        stop_services()
    icon.stop()
    os._exit(0)

def start_services():
    """启动所有服务"""
    global flask_thread
    
    # 启动Syslog服务器
    syslog_server.start()
    
    # 启动邮件采集服务
    email_collector.start()
    
    # 在新线程中启动Flask应用
    if flask_thread is None or not flask_thread.is_alive():
        flask_thread = threading.Thread(target=lambda: app.run(host='0.0.0.0', port=CONFIG['web_port'], debug=False, use_reloader=False))
        flask_thread.daemon = True
        flask_thread.start()
    
    print(f"所有服务已启动，Web界面: http://localhost:{CONFIG['web_port']}")

def stop_services():
    """停止所有服务"""
    # 停止Syslog服务器
    syslog_server.stop()
    
    # 停止邮件采集服务
    email_collector.stop()
    
    print("所有服务已停止")

def run_with_tray():
    """以系统托盘模式运行"""
    global tray_icon, service_running
    
    if not TRAY_AVAILABLE:
        print("系统托盘功能不可用，切换到传统模式")
        run_traditional()
        return
    
    # 创建托盘菜单
    menu = pystray.Menu(
        pystray.MenuItem("开启服务", on_start_service),
        pystray.MenuItem("停止服务", on_stop_service),
        pystray.MenuItem("打开Web界面", on_open_web),
        pystray.Menu.SEPARATOR,
        pystray.MenuItem("退出", on_quit)
    )
    
    # 创建托盘图标
    icon_image = create_tray_icon()
    tray_icon = pystray.Icon("SyslogPush", icon_image, "Syslog推送系统", menu)
    
    # 自动启动服务
    start_services()
    service_running = True
    
    print("系统托盘模式启动，服务已自动开启")
    print(f"Web界面: http://localhost:{CONFIG['web_port']}")
    
    # 运行托盘图标
    tray_icon.run()

def run_traditional():
    """传统模式运行"""
    global service_running
    
    start_services()
    service_running = True
    
    try:
        # 保持主线程运行
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n正在停止服务...")
        stop_services()
        service_running = False

if __name__ == '__main__':
    # 检查是否以系统托盘模式运行
    if len(sys.argv) > 1 and sys.argv[1] == '--tray':
        run_with_tray()
    elif TRAY_AVAILABLE:
        # 默认使用系统托盘模式
        run_with_tray()
    else:
        # 传统模式
        run_traditional()